package com.doeis.client;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

import java.io.IOException;
import java.net.SocketAddress;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.doeis.common.utils.StringUtils;
import com.doeis.minaserver.bean.UserBasic;
import com.doeis.minaserver.packet.InfoPacket;
import com.doeis.minaserver.packet.Packet;
import com.doeis.minaserver.packet.Packet.Direction;
import com.doeis.minaserver.packet.Packet.PacketType;
import com.doeis.minaserver.packet.Packet.ProtocolVersion;
import com.doeis.minaserver.session.ClientConnection;
import com.doeis.uwork.entity.ItemNotes;
import com.doeis.uwork.packet.SystemPacket;

public class NettyClientChannelHandlerAdapter3 extends ChannelHandlerAdapter {
	
	/**
	 * 与客户端的链接管理
	 */
	public static final String CONNECTION = "_client_conn";
	public static final String PACKETHANDLER = "_packet_handler";
	
	
	private String login;
	private String pwd;
	private String userid;
	private String noteid;
	
	public NettyClientChannelHandlerAdapter3( String login, String pwd, String userid, String noteid){
		this.pwd = pwd;
		this.login = login;
		this.userid = userid;
		this.noteid = noteid;
	}
	/**
	 * 与客户端链接最长时间
	 */
//	private static final int MAX_IDLE_TIME = 30 * 60; // 单位是秒
//	private static final int MAX_IDLE_TIME = 20 * 60; // 单位是秒

	private static final Logger log = Logger.getLogger(NettyClientChannelHandlerAdapter3.class);
	
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		
		AttributeKey<PacketHandler> attributeKey = AttributeKey.valueOf(PACKETHANDLER); 
		Attribute<PacketHandler> attribute = ctx.attr(attributeKey);
		PacketHandler packetHandler = attribute.get();
		Packet packet = (Packet)msg;
		
		//进行日志发送
//		sendLog(packet, false);
		
		String from = packet.getFrom();
		String to = packet.getTo();
		if( StringUtils.isBlank(from) || StringUtils.isBlank(to) ){
			throw new NullPointerException("From or to with null value!");
		}
		if( !from.equals(to) ){	
			//这里把业务数据上传到用户层，用户来处理实际业务
			packetHandler.process(packet);
		}
	}

	
	
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		super.channelRegistered(ctx);
		

		PacketHandler packetHandler = new PacketHandler( );
		
		AttributeKey<PacketHandler> attributeKey = AttributeKey.valueOf(PACKETHANDLER); 
		Attribute<PacketHandler> attribute = ctx.attr(attributeKey);
		attribute.set(packetHandler);
		//TODO 这里每次新建一个链接的时候，都会创建这个几个对象 ，是不是需要改进
		
	}



	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.handlerAdded(ctx);
	}



	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.handlerRemoved(ctx);
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.channelActive(ctx);
		
		//發送登錄消息
		InfoPacket packet = new InfoPacket();
		packet.setDirection(Direction.c2s);
		packet.setPacketType(PacketType.info);
		packet.setVersion(ProtocolVersion.V1_0_0);		
		packet.setTo( Packet.SERVER_ID );
		packet.setFrom( userid );
		packet.setCmd(InfoPacket.CMD_USER_LOGIN);
		UserBasic userBasic = new UserBasic();
		userBasic.setLogin(login);
		userBasic.setName("conca");
		userBasic.setPwd(pwd);
		userBasic.setUserid(userid);
		packet.setBodyObj(userBasic);
		ctx.writeAndFlush(packet);
		
		
		packet.setDirection(Direction.c2s);
		packet.setPacketType(PacketType.info);
		packet.setVersion(ProtocolVersion.V1_0_0);		
		packet.setTo( Packet.SERVER_ID );
		packet.setFrom( userid );
		packet.setCmd(InfoPacket.CMD_USER_LOGIN);
		userBasic = new UserBasic();
		userBasic.setLogin(login);
		userBasic.setName("conca");
		userBasic.setPwd(pwd);
		userBasic.setUserid(userid);
		packet.setBodyObj(userBasic);
		ctx.writeAndFlush(packet);
		
		
		
				
		int i = 0;
		//發送登錄消息
		SystemPacket packet2 = new SystemPacket();
		packet2.setDirection(Direction.c2s);
		packet2.setPacketType(PacketType.system);
		packet2.setVersion(ProtocolVersion.V1_0_0);		
		packet2.setTo( Packet.SERVER_ID );
		packet2.setFrom(userid );
		packet2.setCmd(SystemPacket.NOTIFY_ITEM_NOTE);
		ItemNotes itemNotes = new ItemNotes();
		itemNotes.setId(noteid);
		packet2.setBody(JSON.toJSONString(itemNotes));
		ctx.writeAndFlush(packet2);
		
	}



	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.channelInactive(ctx);
	}



	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
			throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.userEventTriggered(ctx, evt);
	}



	@Override
	public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
			SocketAddress localAddress, ChannelPromise promise)
			throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.connect(ctx, remoteAddress, localAddress, promise);
	}



	@Override
	public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
			throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.disconnect(ctx, promise);
	}



	@Override
	public void close(ChannelHandlerContext ctx, ChannelPromise promise)
			throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.close(ctx, promise);
		closeClientConnection(ctx);
	}



	@Override
	public void read(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.read(ctx);
	}



	@Override
	public void write(ChannelHandlerContext ctx, Object msg,
			ChannelPromise promise) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.write(ctx, msg, promise);
	}



	@Override
	public void flush(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		super.flush(ctx);
	}


  
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		ctx.flush();
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		log.error( " ctx.channel().id(): " + ctx.channel().id().toString());
		
		AttributeKey<ClientConnection> attributeKey = AttributeKey.valueOf(CONNECTION); 
		Attribute<ClientConnection> attribute = ctx.attr(attributeKey);
		ClientConnection clienConn = attribute.get();
		clienConn.close();
		
		String msg = cause.getMessage();		
		if (cause instanceof IOException) {
//			log.error(msg, cause);
		}else {
			log.error(msg, cause);
		}	
		ctx.close();
	}
	
	
	/**
	 * 任何连接被关闭的情况都会调用本方法
	 * @param ioSession
	 */
	private void closeClientConnection(ChannelHandlerContext ctx) {
	}
}
